home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Freeware / Griffith 0.9.8 / griffith-0.9.8-win32.exe / {app} / lib / movie.py < prev    next >
Text File  |  2008-11-17  |  10KB  |  378 lines

  1. # -*- coding: UTF-8 -*-
  2.  
  3. __revision__ = '$Id: movie.py 1040 2008-11-15 21:13:49Z mikej06 $'
  4.  
  5. # Copyright (c) 2005-2008 Vasco Nunes, Piotr O┼╝arowski
  6. #
  7. # This program is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation; either version 2 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. # GNU Library General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program; if not, write to the Free Software
  19. # 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  20.  
  21. # You may use and distribute this software under the terms of the
  22. # GNU General Public License, version 2 or later
  23.  
  24. from urllib import *
  25. import sys
  26. import string
  27. import gutils
  28. import gtk
  29. import os
  30. import os.path
  31. import threading
  32. import time
  33. import tempfile
  34.  
  35. class Movie:
  36.     cast = None
  37.     classification = None
  38.     country = None
  39.     director = None
  40.     genre = None
  41.     image = None
  42.     notes = None
  43.     number = None
  44.     o_site = None
  45.     o_title = None
  46.     plot = None
  47.     rating = None
  48.     runtime = None
  49.     site = None
  50.     studio = None
  51.     title = None
  52.     trailer = None
  53.     year = None
  54.     
  55.     movie_id = None
  56.     debug = False
  57.     locations = None
  58.     engine_author = None
  59.     engine_description = None
  60.     engine_language = None
  61.     engine_name = None
  62.     engine_version = None
  63.     page = None
  64.     url = None
  65.     image_url = None
  66.     encode = 'iso-8859-1'
  67.     fields_to_fetch = []
  68.     progress = None
  69.  
  70.     # functions that plugin should implement: {{{
  71.     def initialize(self):
  72.         pass
  73.     def get_cast(self):
  74.         pass
  75.     def get_classification(self):
  76.         pass
  77.     def get_country(self):
  78.         pass
  79.     def get_director(self):
  80.         pass
  81.     def get_genre(self):
  82.         pass
  83.     def get_image(self):
  84.         pass
  85.     def get_notes(self):
  86.         pass
  87.     def get_o_site(self):
  88.         pass
  89.     def get_o_title(self):
  90.         pass
  91.     def get_plot(self):
  92.         pass
  93.     def get_rating(self):
  94.         pass
  95.     def get_runtime(self):
  96.         pass
  97.     def get_site(self):
  98.         pass
  99.     def get_studio(self):
  100.         pass
  101.     def get_title(self):
  102.         pass
  103.     def get_trailer(self):
  104.         pass
  105.     def get_year(self):
  106.         pass
  107.     #}}}
  108.  
  109.     def __getitem__(self, key):
  110.         return getattr(self,key)
  111.     def __setitem__(self, key, value):
  112.         setattr(self,key,value)
  113.     
  114.     def get_movie(self, parent_window=None):
  115.         try:
  116.             #
  117.             # initialize the progress dialog once for the following loading process
  118.             #
  119.             if self.progress is None:
  120.                 self.progress = Progress(parent_window)
  121.             self.progress.set_data(parent_window, _("Fetching data"), _("Wait a moment"), True)
  122.             #            
  123.             # get the page
  124.             #
  125.             self.open_page(parent_window)
  126.         except:
  127.             # close the dialog if an error occured
  128.             self.progress.hide()
  129.             # reraise the error
  130.             raise
  131.  
  132.     def open_page(self, parent_window=None, url=None):
  133.         if url is None:
  134.             url_to_fetch = self.url
  135.         else:
  136.             url_to_fetch = url
  137.         if parent_window is not None:
  138.             self.parent_window = parent_window
  139.         self.progress.set_data(parent_window, _("Fetching data"), _("Wait a moment"), False)
  140.         retriever = Retriever(url_to_fetch, self.parent_window, self.progress)
  141.         retriever.start()
  142.         while retriever.isAlive():
  143.             self.progress.pulse()
  144.             if self.progress.status:
  145.                 retriever.suspend()
  146.             while gtk.events_pending():
  147.                 gtk.main_iteration()
  148.         try:
  149.             ifile = file(retriever.html[0], "rb")
  150.             data = ifile.read()
  151.         except IOError:
  152.             pass
  153.         if url is None:
  154.             self.page = data
  155.         return data
  156.         urlcleanup()
  157.  
  158.     def fetch_picture(self):
  159.         if self.image_url:
  160.             tmp_dest = tempfile.mktemp(prefix='poster_', dir=self.locations['temp'])
  161.             self.image = tmp_dest.split('poster_', 1)[1]
  162.             dest = "%s.jpg" % tmp_dest
  163.             try:
  164.                 self.progress.set_data(self.parent_window, _("Fetching poster"), _("Wait a moment"), False)
  165.                 retriever = Retriever(self.image_url, self.parent_window, self.progress, dest)
  166.                 retriever.start()
  167.                 while retriever.isAlive():
  168.                     self.progress.pulse()
  169.                     if self.progress.status:
  170.                         retriever.suspend()
  171.                     while gtk.events_pending():
  172.                         gtk.main_iteration()
  173.                 urlcleanup()
  174.             except:
  175.                 self.image = ""
  176.                 try:
  177.                     os.remove("%s.jpg" % tmp_dest )
  178.                 except:
  179.                     print "Can't remove %s file" % tmp_dest # FIXME: use debug.show()
  180.         else:
  181.             self.image = ""
  182.  
  183.     def parse_movie(self):
  184.         try:
  185.             from copy import deepcopy
  186.             fields = deepcopy(self.fields_to_fetch)
  187.  
  188.             self.initialize()
  189.  
  190.             if 'year' in fields:
  191.                 self.get_year()
  192.                 self.year = gutils.digits_only(self.year, 2100)
  193.                 fields.pop(fields.index('year'))
  194.             if 'runtime' in fields:
  195.                 self.get_runtime()
  196.                 self.runtime = gutils.digits_only(self.runtime)
  197.                 fields.pop(fields.index('runtime'))
  198.             if 'rating' in fields:
  199.                 self.get_rating()
  200.                 self.rating = gutils.digits_only(self.rating, 10)
  201.                 fields.pop(fields.index('rating'))
  202.             if 'cast' in fields:
  203.                 self.get_cast()
  204.                 self.cast = gutils.clean(self.cast)
  205.                 self.cast = gutils.gdecode(self.cast, self.encode)
  206.                 fields.pop(fields.index('cast'))
  207.             if 'plot' in fields:
  208.                 self.get_plot()
  209.                 self.plot = gutils.clean(self.plot)
  210.                 self.plot = gutils.gdecode(self.plot, self.encode)
  211.                 fields.pop(fields.index('plot'))
  212.             if 'notes' in fields:
  213.                 self.get_notes()
  214.                 self.notes = gutils.clean(self.notes)
  215.                 self.notes = gutils.gdecode(self.notes, self.encode)
  216.                 fields.pop(fields.index('notes'))
  217.             if 'image' in fields:
  218.                 self.get_image()
  219.                 self.fetch_picture()
  220.                 fields.pop(fields.index('image'))
  221.  
  222.             for i in fields:
  223.                 getattr(self, "get_%s" % i)()
  224.                 self[i] = gutils.clean(self[i])
  225.                 self[i] = gutils.gdecode(self[i], self.encode)
  226.         
  227.             if 'o_title' in self.fields_to_fetch and self.o_title is not None:
  228.                 if self.o_title[:4] == 'The ':
  229.                     self.o_title = self.o_title[4:] + ', The'
  230.             if 'title' in self.fields_to_fetch and self.title is not None:
  231.                 if self.title[:4] == 'The ':
  232.                     self.title = self.title[4:] + ', The'
  233.         finally:
  234.             # close the progress dialog which was opened in get_movie
  235.             self.progress.hide()
  236.  
  237. class SearchMovie:
  238.     page = None
  239.     number_results = None
  240.     titles = [""]
  241.     ids = [""]
  242.     url = None
  243.     encode = 'utf-8'
  244.     original_url_search = None
  245.     translated_url_search = None
  246.     elements = None
  247.     title = None
  248.     remove_accents = True
  249.     progress = None
  250.  
  251.     def __init__(self):
  252.         pass
  253.  
  254.     def search_movies(self,parent_window):
  255.         try:
  256.             #
  257.             # initialize the progress dialog once for the following search process
  258.             #
  259.             if self.progress is None:
  260.                 self.progress = Progress(parent_window)
  261.             self.progress.set_data(parent_window, _("Searching"), _("Wait a moment"), True)
  262.             #            
  263.             # call the plugin specific search method
  264.             #
  265.             self.search(parent_window)
  266.         finally:
  267.             # dont forget to hide the progress dialog
  268.             self.progress.hide()
  269.  
  270.     def open_search(self,parent_window):
  271.         self.titles = [""]
  272.         self.ids = [""]
  273.         if self.url.find('%s') > 0:
  274.             self.url = self.url % self.title
  275.             self.url = string.replace(self.url, ' ', '%20')
  276.         else:
  277.             self.url = string.replace(self.url+self.title,' ','%20')
  278.         try:
  279.             url = self.url.encode(self.encode)
  280.         except UnicodeEncodeError:
  281.             url = self.url.encode('utf-8')
  282.         self.progress.set_data(parent_window, _("Searching"), _("Wait a moment"), False)
  283.         retriever = Retriever(url, parent_window, self.progress)
  284.         retriever.start()
  285.         while retriever.isAlive():
  286.             self.progress.pulse()
  287.             if self.progress.status:
  288.                 retriever.suspend()
  289.             while gtk.events_pending():
  290.                 gtk.main_iteration()
  291.         try:
  292.             ifile = file(retriever.html[0], "rb")
  293.             self.page = ifile.read()
  294.         except IOError:
  295.             pass
  296.         urlcleanup()
  297.  
  298. class Retriever(threading.Thread):
  299.     def __init__(self, URL, parent_window, progress, destination=None):
  300.         self.URL = URL
  301.         self.html = None
  302.         self.destination = destination
  303.         self.parent_window = parent_window
  304.         self.progress = progress
  305.         self._stopevent = threading.Event()
  306.         self._sleepperiod = 1.0
  307.         threading.Thread.__init__(self, name="Retriever")
  308.     def run(self):
  309.         try:
  310.             self.html = urlretrieve(self.URL, self.destination, self.hook)
  311.             #self.html = urlretrieve(self.URL.encode('utf-8'), self.destination, self.hook)
  312.             if self.progress.status:
  313.                 self.html = []
  314.         except IOError:
  315.             self.progress.dialog.hide()
  316.             gutils.urllib_error(_("Connection error"), self.parent_window)
  317.             self.suspend()
  318.     def hook(self,count, blockSize, totalSize):
  319.         if totalSize ==-1:
  320.             pass
  321.         else:
  322.             try:
  323.                 downloaded_percentage = min((count*blockSize*100)/totalSize, 100)
  324.             except:
  325.                 downloaded_percentage = 100
  326.             if count != 0:
  327.                 downloaded_kbyte = int(count * blockSize/1024.0)
  328.                 filesize_kbyte = int(totalSize/1024.0)
  329.  
  330. #
  331. # use own derived URLopener class because we need to set a correct User-Agent
  332. # string for some web sites. The default is 'Python-urllib/<version>'
  333. # which not all sites accepting. (zelluloid.de for example)
  334. #
  335. _uaurlopener = None
  336. def urlretrieve(url, filename=None, reporthook=None, data=None):
  337.     global _uaurlopener
  338.     if not _uaurlopener:
  339.         _uaurlopener = UAFancyURLopener()
  340.     return _uaurlopener.retrieve(url, filename, reporthook, data)
  341.  
  342. class UAFancyURLopener(FancyURLopener):
  343.     # use Firefox 3.0 User-Agent string from Windows XP
  344.     version = 'Mozilla/5.0 (Windows; U; Windows NT 6.0) Gecko/2008052906 Firefox/3.0'
  345.     
  346. class Progress:
  347.     def __init__(self, window, title = '', message = ''):
  348.         self.status = False
  349.         self.dialog = gtk.Dialog(title, window, gtk.DIALOG_MODAL, ())
  350.         self.dialog.set_urgency_hint(False)
  351.         self.label = gtk.Label()
  352.         self.label.set_markup(message)
  353.         self.dialog.vbox.pack_start(self.label)
  354.         self.progress = gtk.ProgressBar()
  355.         self.progress.set_pulse_step(0.01)
  356.         self.dialog.vbox.pack_start(self.progress, False, False)
  357.         self.button = gtk.Button(_("Cancel"), gtk.STOCK_CANCEL)
  358.         self.button.connect("clicked", self.callback)
  359.         self.dialog.vbox.pack_start(self.button, False, False)
  360.         self.dialog.show_all()
  361.     def callback(self, widget):
  362.         self.dialog.hide()
  363.         self.status = True
  364.     def pulse(self):
  365.         self.progress.pulse()
  366.         time.sleep(0.01)
  367.     def close(self):
  368.         self.dialog.destroy()
  369.     def hide(self):
  370.         self.dialog.hide()
  371.     def set_data(self, parent_window, title, message, showit):
  372.         #self.dialog.set_parent(parent_window)
  373.         self.dialog.set_title(title)
  374.         self.label.set_markup(message)
  375.         if showit == True:
  376.             self.dialog.show()
  377. # vim: fdm=marker
  378.